package org.acme.job.factory;

import org.acme.job.constant.SysJobConstant;
import org.acme.job.handler.SysJobHandler;
import org.acme.job.po.SysJob;
import org.acme.job.service.SysJobService;
import org.acme.job.utils.TimeUtils;
import org.acme.server.service.SysServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author chentao
 * @version 1.0
 * @description: TODO
 * @date 2025/3/8 下午12:14
 */
@Service
public class SysJobFactory implements InitializingBean, DisposableBean {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${job.max.retry-size:10}")
    private int maxRetrySize;

    @Value("${job.max.limit-size:10}")
    private int maxLimitSize;

    @Value("${job.retry.rate:60}")
    private int retryRate;

    @Resource
    private SysJobService sysJobService;

    @Resource
    private SysServerService sysServerService;

    @Resource
    private SysJobHandler sysJobHandler;

    private ExecutorService executorService = new ScheduledThreadPoolExecutor(10);

    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    @Override
    public void destroy() throws Exception {
        this.executorService.shutdownNow();
        this.scheduledThreadPoolExecutor.shutdownNow();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.executorService = new ScheduledThreadPoolExecutor(10);
        this.scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(10);
        this.scheduledThreadPoolExecutor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                try {
                    long serverId = sysServerService.getServerId();
                    List<SysJob> joblist = sysJobService.getJobList(serverId, maxRetrySize, maxLimitSize);
                    if (!joblist.isEmpty()) {
                        CountDownLatch countDownLatch = new CountDownLatch(joblist.size());
                        for (SysJob sysJob : joblist) {
                            executorService.execute(new SysJobHandleThread(sysJob));
                            countDownLatch.countDown();
                        }
                        countDownLatch.await();
                    }
                } catch (Exception e) {
                    logger.warn("任务执行失败: " + e.getMessage());
                }
            }
        }, 0, 10, TimeUnit.SECONDS);
    }

    /****
     * 任务执行的类
     */
    class SysJobHandleThread implements Runnable {

        private SysJob sysJob;

        public SysJobHandleThread(SysJob sysJob) {
            this.sysJob = sysJob;
        }

        @Override
        public void run() {
            int size = sysJob.getRetrySize();
            try {
                sysJob.setStatus(SysJobConstant.SUCCESS);
                sysJob.setRetrySize(size + 1);
                sysJobHandler.handle(sysJob);
            } catch (Exception e) {
                Date nextTime = TimeUtils.getTime(retryRate * (size + 1));
                sysJob.setRetryTime(nextTime);
                sysJob.setStatus(SysJobConstant.ERROR);
            } finally {
                sysJob.recalculateFields();
                sysJobService.saveOrUpdate(sysJob);
            }
        }
    }
}
